package heap

import "lesson01/classfile"

type FieldRef struct {
	MemberRef
	field *Field
}

func newFieldRef(cp *ConstantPool, refInfo *classfile.ConstantFieldrefInfo) *FieldRef {
	field := &FieldRef{}
	field.cp = cp
	field.copyMemberRefInfo(&refInfo.ConstantMemberrefInfo)
	return field
}

func (e *FieldRef) ResolvedField() *Field {
	if e.field == nil {
		e.resolveFieldRef()
	}
	return e.field
}

// resolveFieldRef 解析属性引用
func (e *FieldRef) resolveFieldRef() {
	d := e.cp.class
	class := e.ResolvedClass()
	field := lookupField(class, e.name, e.descriptor)

	if field == nil {
		panic("java.lang.NoSuchFieldError")
	}

	if !field.isAccessibleTo(d) {
		panic("java.lang.IllegalAccessError")
	}

	e.field = field
}

func lookupField(c *Class, name, descriptor string) *Field {
	for _, field := range c.fields {
		if field.name == name && field.descriptor == descriptor {
			return field
		}
	}

	for _, f := range c.interfaces {
		if field := lookupField(f, name, descriptor); field != nil {
			return field
		}
	}

	if c.superClass != nil {
		return lookupField(c.superClass, name, descriptor)
	}
	return nil
}
